package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 *如果想统计所有部门管理的业务方法执行耗时，那所有的部门管理的业务方法都是原始业务方法。面向这样的指定的一个或多个方法进行编程，称为面向切面编程
 *AOP面向切面编程和OOP面向对象编程一样，它们都仅仅是一种编程思想，而动态代理技术是这种思想最主流的实现方式。而Spring的AOP是Spring框架的高级技术，旨在管理bean对象的过程中底层使用动态代理机制，对特定的方法进行编程(功能增强)。
 * 1. 减少重复代码
 * 2. 提高开发效率
 * 3. 维护方便
 * 常见的应用场景如下：
 * - 记录系统的操作日志
 * - 权限控制
 * - 事务管理：我们前面所讲解的Spring事务管理，底层其实也是通过AOP来实现的，只要添加@Transactional注解之后，AOP程序自动会在原始方法运行前先来开启事务，在原始方法运行完毕之后提交或回滚事务
 *
 */
@Component   //把当前类交给ioc容器管理
@Aspect   //表示当前类为切面类
@Slf4j
public class TimeAspect {

    //指定对哪些特定的方法编程,第一个*是方法的返回值，第二个*是类名，第三个*是方法名
    //说明com.itheima.service这个包下所有接口或者方法都会运行这个方法中所封装的公共的逻辑代码，
    //这个表达式称为切入点表达式
    @Around("execution(* com.itheima.service.*.*(..))")

    public Object recordTime(ProceedingJoinPoint JoinPoint) throws Throwable{
        //记录方法执行开始时间
        long begin = System.currentTimeMillis();

        //调用原始方法运行
        Object result = JoinPoint.proceed();

        //记录方法执行结束时间
        long end = System.currentTimeMillis();

        //计算方法执行耗时,JoinPoint.getSignature是拿到方法签名
        log.info(JoinPoint.getSignature()+"执行耗时:{}ms",end-begin);

        return result;


    }
}
